﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading.Tasks;
using CaltechSoft.Service.EntityFW.Entity;
using System.Data.Entity;
using CaltechSoft.Service.Infrastructure.Utility;


namespace CaltechSoft.Service.Repositories
{
    public class PoRepository : BaseRepository<Po>
    {
        private static List<Po> mock = new List<Po>();

        public override async Task<int> Add(Po entity)
        {
            Guard.Against<Exception>(!(entity.CompanyId > 0), "Customer can not be null!");
            Guard.Against<Exception>(string.IsNullOrWhiteSpace(entity.QuoteNumber), "Quote Number can not be null!");

            using (var context = Context)
            {
                int customerId;
                string companyName;

                if (entity.Company != null)
                {
                    context.Customers.Add(entity.Company);
                    await context.SaveChangesAsync();
                    entity.CompanyId = entity.Company.Id;
                    customerId = entity.Company.Id;
                    companyName = entity.Company.Name;
                }
                else
                {
                    customerId = entity.CompanyId;
                    companyName = context.Customers.FirstOrDefault(x => x.Id == customerId).Name;
                }

                if (entity.Salesman != null)
                {
                    context.Users.Add(entity.Salesman);
                    entity.Salesman.UserName = entity.Salesman.FirstName + entity.Salesman.LastName;
                    entity.Salesman.Id = Guid.NewGuid().ToString();
                    await context.SaveChangesAsync();
                }
                //Add sale manager checkbox
                if (entity.ShowFullName)
                {
                    entity.ManagerId = entity.CreatedBy;
                }


                var numberOfPo = context.Pos.Count(x => x.CreatedDate.HasValue && x.CreatedDate.Value.Year == DateTime.Now.Year && x.CreatedDate.Value.Month == DateTime.Now.Month && x.CreatedDate.Value.Day == DateTime.Now.Day);
                if (entity.PODate.HasValue)
                {
                    numberOfPo = context.Pos.Count(x => x.PODate.HasValue && x.PODate.Value.Year == entity.PODate.Value.Year && x.PODate.Value.Month == entity.PODate.Value.Month && x.PODate.Value.Day == entity.PODate.Value.Day);
                }

                var poNumber = GetPoNumber(context.Pos, numberOfPo, entity.PODate);
                entity.PoNumber = poNumber;

                foreach (var item in entity.Items)
                {
                    context.PoItems.Add(item);
                    var existCustomerEquipment = context.CustomerEquipments.Any(n => n.CustomerId == entity.CompanyId && n.EquipmentId == item.EquipmentId);
                    if (!existCustomerEquipment)
                    {
                        var customerEquipment = GenerateCustomerEquipment(entity, item);
                        context.CustomerEquipments.Add(customerEquipment);
                    }
                }

                context.Pos.Add(entity);
                return await context.SaveChangesAsync();
            }
        }

        private string GetPoNumber(DbSet<Po> context, int number, DateTime? poDate)
        {
            number++;
            var poNumber = "PO" + (poDate.HasValue ? poDate.Value.ToString("MMddyy") : DateTime.Now.ToString("MMddyy")) + "-" + number.ToString("000");
            if (context.Where(n => n.PoNumber.Equals(poNumber)).Any())
            {
                poNumber = GetPoNumber(context, number, poDate);
                return poNumber;
            }
            else
            {
                return poNumber;
            }
        }

        public override async Task<int> Update(Po updatedEntity)
        {
            Guard.Against<Exception>(!(updatedEntity.CompanyId > 0), "Customer can not be null!");
            Guard.Against<Exception>(string.IsNullOrWhiteSpace(updatedEntity.QuoteNumber), "Quote Number can not be null!");

            using (var context = Context)
            {
                var updateEntry = context.Entry(updatedEntity);
                if (updateEntry.State == EntityState.Detached)
                {
                    var curAttachedEntity = context.Set<Po>().FirstOrDefault(i => i.Id == updatedEntity.Id);

                    if (curAttachedEntity != null)
                    {
                        var attachedEntry = context.Entry(curAttachedEntity);
                        attachedEntry.CurrentValues.SetValues(updatedEntity);
                        var listModified = attachedEntry.CurrentValues.PropertyNames.Where(p => attachedEntry.Property(p).IsModified).ToList();

                        if (listModified.Contains("ShowFullName") && updatedEntity.ShowFullName)
                        {
                            updatedEntity.ManagerId = updatedEntity.UpdatedBy;
                        }

                        if (listModified.Count == 3 && listModified.Contains("ShowFullName") && listModified.Contains("UpdatedBy") && listModified.Contains("UpdatedDate"))
                        {
                            attachedEntry.Property(e => e.UpdatedBy).IsModified = false;
                            updatedEntity.UpdatedBy = curAttachedEntity.UpdatedBy;
                        }
                    }
                    else
                    {
                        updateEntry.State = EntityState.Modified;
                    }
                }
                if (updatedEntity.Company != null)
                {
                    context.Customers.Attach(updatedEntity.Company);
                    var customerEntry = context.Entry(updatedEntity.Company);
                    customerEntry.Property(e => e.Email).IsModified = true;
                    customerEntry.Property(e => e.Address).IsModified = true;
                    customerEntry.Property(e => e.ContactPersonName).IsModified = true;
                    customerEntry.Property(e => e.Tel).IsModified = true;
                    customerEntry.Property(e => e.Mobile).IsModified = true;
                    customerEntry.Property(e => e.Name).IsModified = true;

                }

                if (updatedEntity.Salesman != null)
                {
                    updatedEntity.Salesman.UserName = updatedEntity.Salesman.LastName;
                    context.Users.Attach(updatedEntity.Salesman);
                    var salemanEntry = context.Entry(updatedEntity.Salesman);
                    salemanEntry.Property(e => e.Email).IsModified = true;
                    salemanEntry.Property(e => e.Tel).IsModified = true;
                    salemanEntry.Property(e => e.PhoneNumber).IsModified = true;
                    salemanEntry.Property(e => e.LastName).IsModified = true;
                }


                var attachedEntity = await context.Pos.FirstOrDefaultAsync(x => x.Id == updatedEntity.Id);

                context.PoItems.RemoveRange(attachedEntity.Items);

                foreach (var item in updatedEntity.Items)
                {
                    item.PoId = updatedEntity.Id;
                    context.PoItems.Add(item);

                    var existCustomerEquipment = context.CustomerEquipments.Any(n => n.CustomerId == updatedEntity.CompanyId && n.EquipmentId == item.EquipmentId);
                    if (!existCustomerEquipment)
                    {
                        var customerEquipment = GenerateCustomerEquipment(updatedEntity, item);
                        context.CustomerEquipments.Add(customerEquipment);
                    }
                }

                await context.SaveChangesAsync();

                return await base.Update(updatedEntity);
            }
        }


        private CustomerEquipment GenerateCustomerEquipment(Po po, PoItem poItem)
        {
            var customerEquipment = new CustomerEquipment();
            customerEquipment.CustomerId = po.CompanyId;
            customerEquipment.EquipmentId = poItem.EquipmentId;
            customerEquipment.Price = poItem.UnitPrice;
            customerEquipment.CalibrationDate = DateTime.Now;
            customerEquipment.NextDueDate = DateTime.Now.AddYears(1);
            customerEquipment.CreatedBy = po.CreatedBy;
            customerEquipment.CreatedDate = DateTime.Now;

            return customerEquipment;
        }
    }
}
